package org.jili.novoland.base;

import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Rect;
import android.util.Log;

public class Sprite extends Layer {
    // transform constants
    public static final int TRANS_NONE = 0;
    public static final int TRANS_ROT90 = 5;
    public static final int TRANS_ROT180 = 3;
    public static final int TRANS_ROT270 = 6;
    public static final int TRANS_MIRROR = 2;
    public static final int TRANS_MIRROR_ROT90 = 7;
    public static final int TRANS_MIRROR_ROT180 = 1;
    public static final int TRANS_MIRROR_ROT270 = 4;

    private int sequenceIndex;
    private int[] sequence;

    private Bitmap img;
    private int numStaticFrames;
    private int[] srcFrameX;
    private int[] srcFrameY;

    protected int col, row;

    public Sprite(int tileWidth, int tileHeight, Bitmap img) {
        this(tileWidth, tileHeight, img, img.getWidth(), img.getHeight());
    }

    public Sprite(int tileWidth, int tileHeight, Bitmap inImg, int frameWidth, int frameHeight) {
        super(tileWidth, tileHeight, frameWidth, frameHeight);
        setImage(inImg, frameWidth, frameHeight);

    }

    public void setFrameSequence(int[] sequence) {
        if (sequence == null) {
            // return to default sequence
            this.sequence = null;
            return;
        }

        int l = sequence.length;

        if (l == 0)
            throw new IllegalArgumentException();

        for (int i = 0; i < l; i++) {
            if (sequence[i] > numStaticFrames || sequence[i] < 0)
                throw new ArrayIndexOutOfBoundsException();
        }

        this.sequence = sequence;
        this.sequenceIndex = 0;
    }

    public final int getFrame() {
        return sequenceIndex;
    }

    public int getFrameSequenceLength() {
        return (sequence == null) ? numStaticFrames : sequence.length;
    }

    public void setFrame(int frame) {
        if (frame < 0 || frame >= ((sequence == null) ? numStaticFrames : sequence.length)) {
            throw new IndexOutOfBoundsException();
        }
        this.sequenceIndex = frame;
    }

    public void nextFrame() {
        if (sequenceIndex >= ((sequence == null) ? numStaticFrames : sequence.length) - 1)
            sequenceIndex = 0;
        else
            sequenceIndex++;
    }

    public void prevFrame() {
        if (sequenceIndex == 0)
            sequenceIndex = ((sequence == null) ? numStaticFrames : sequence.length) - 1;
        else
            sequenceIndex--;
    }

    public void setImage(Bitmap inImg, int frameWidth, int frameHeight) {
        if (inImg == null)
            throw new NullPointerException();
        int imageW = inImg.getWidth();
        int imageH = inImg.getHeight();

        if ((frameWidth < 1 || frameHeight < 1) || ((imageW % frameWidth) != 0) || ((imageH % frameHeight) != 0)) {
            throw new IllegalArgumentException();
        }
        this.img = inImg;

        this.numStaticFrames = (imageW / frameWidth) * (imageH / frameHeight);

        this.srcFrameX = new int[numStaticFrames];
        this.srcFrameY = new int[numStaticFrames];
        int srcIndex = 0;
        for (int j = 0; j < imageH; j += frameHeight) {
            for (int i = 0; i < imageW; i += frameWidth) {
                this.srcFrameX[srcIndex] = i;
                // Log.v(TiledLayer.class.getName(),
                // Integer.toString(i) + "," + Integer.toString(j) + ","
                // + Integer.toString(srcIndex));
                this.srcFrameY[srcIndex] = j;
                srcIndex++;
            }
        }

    }

    public void paint(int viewX, int viewY, Canvas g) {
        if (!isVisible())
            return;

        int frame = (sequence == null) ? sequenceIndex : sequence[sequenceIndex];
        paintFrame(viewX, viewY, g, col, row, frame);

    }

    protected void paintFrame(int viewX, int viewY, Canvas g, int inCol, int inRow, int frame) {
        Rect srcRect = new Rect(srcFrameX[frame], srcFrameY[frame], srcFrameX[frame] + getWidth(), srcFrameY[frame]
                + getHeight());
        int tx = viewX + inCol * getTileWidth() + getTileWidth() - getWidth();
        int ty = viewY + inRow * getTileHeight() + getTileHeight() - getHeight();
        Rect dstRect = new Rect(tx, ty, tx + getWidth(), ty + getHeight());
        g.drawBitmap(img, srcRect, dstRect, null);

    }

    public void setMatrixPosition(int inCol, int inRow) {
        col = inCol;
        row = inRow;
    }

    public int getCol() {
        return col;
    }

    public int getRow() {
        return row;
    }

}
